# Replication data for:
# The CJEU Database Platform: Decisions and Decision-Makers
# Journal of Law and Courts
# Stein Arne Brekke
# Joshua C. Fjelstul
# Silje Synnove Lyder Hermansen
# Daniel Naurin

# Install packages from GitHub
devtools::install_github("jfjelstul/eums")
devtools::install_github("jfjelstul/eumaps", ref = "v.0.1.1")
devtools::install_github("jfjelstul/ggminimal", ref = "v.0.1.0")
devtools::install_github("jfjelstul/alluvialplots", ref = "v.0.1.0")

# Packages
library(tidyverse)
library(lubridate)
library(ggplot2)
library(patchwork)
library(eums)
library(eumaps)
library(ggminimal)
library(alluvialplots)

# Read in data -----------------------------------------------------------------

# Judgments
load("judgments.RData")

# Assignments
load("assignments.RData")

# Application 1: Discretion in the judicial process ----------------------------

# Collapse by proceeding
proceedings <- judgments |>
  group_by(iuropa_proceeding_id) |>
  summarize(
    court = court[1],
    panel_size = panel_size[1],
    proceeding_year = proceeding_year[1],
    decision_year = min(decision_year),
    ag_opinion = as.numeric(sum(ag_opinion) > 0),
    direct_action = as.numeric(sum(direct_action) > 0),
    preliminary_ruling = as.numeric(sum(preliminary_ruling) > 0),
  ) |>
  filter(direct_action == 1 | preliminary_ruling == 1)

# Code variables
proceedings <- proceedings |>
  mutate(
    panel_group = case_when(
      panel_size == 3 ~ "Small panel",
      panel_size == 5 ~ "Medium panel",
      panel_size > 5 ~ "Large panel",
      TRUE ~ "Other"
    ),
    ag_opinion_status = case_when(
      ag_opinion == 1 ~ "AG opinion",
      TRUE ~ "No AG opinion"
    ),
    proceeding_type = case_when(
      direct_action == 1 ~ "Direct actions",
      preliminary_ruling == 1 ~ "References for a preliminary ruling",
      TRUE ~ "Other"
    )
  ) |>
  filter(panel_group != "Other")

## AG opinions -----------------------------------------------------------------

# Collapse data by proceeding type
plot_data <- proceedings |>
  filter(
    proceeding_year >= 1989 &
      proceeding_year <= 2021 &
      court == "Court of Justice"
  ) |>
  group_by(proceeding_type, panel_group, ag_opinion_status) |>
  summarize(count = n())

# Order factors
plot_data <- plot_data |>
  mutate(
    proceeding_type = proceeding_type |>
      factor(
        levels = c(
          "References for a preliminary ruling",
          "Direct actions"
        )
      ),
    panel_group = panel_group |>
      factor(
        levels = c(
          "Small panel",
          "Medium panel",
          "Large panel"
        )
      ),
    ag_opinion_status = ag_opinion_status |>
      factor(
        levels = c(
          "No AG opinion",
          "AG opinion"
        )
      )
  )

# Make alluvial plot
plot <- make_alluvial_plot(
  plot_data$proceeding_type, plot_data$panel_group, plot_data$ag_opinion_status,
  frequency = plot_data$count,
  fill = plot_data$proceeding_type,
  palette = c("gray70", "gray30"),
  alpha = 0.3,
  axis_labels = c("Proceeding type", "Panel size", "AG opinion"),
  width_axes = 1,
  width_gaps = 0.2,
  return_data = FALSE,
  size_category_labels = 10,
  guide = FALSE
)

# Save plot
ggsave("AG_opinions.pdf", plot, scale = 1.25, width = 10, height = 6)

## Descriptive statistics ------------------------------------------------------

# Percent of proceedings with an AG opinion
sum(plot_data$count[plot_data$ag_opinion_status == "AG opinion"]) / sum(plot_data$count)

# Percent of proceedings that go to a medium panel
sum(plot_data$count[plot_data$panel_group == "Medium panel" & plot_data$proceeding_type == "References for a preliminary ruling"]) / sum(plot_data$count[plot_data$proceeding_type == "References for a preliminary ruling"])

# Percent of proceedings with each panel size that have an AG opinion
sum(plot_data$count[plot_data$panel_group == "Small panel" & plot_data$ag_opinion_status == "AG opinion"]) / sum(plot_data$count[plot_data$panel_group == "Small panel"])
sum(plot_data$count[plot_data$panel_group == "Medium panel" & plot_data$ag_opinion_status == "AG opinion"]) / sum(plot_data$count[plot_data$panel_group == "Medium panel"])
sum(plot_data$count[plot_data$panel_group == "Large panel" & plot_data$ag_opinion_status == "AG opinion"]) / sum(plot_data$count[plot_data$panel_group == "Large panel"])

## AG opinions over time -------------------------------------------------------

# Collapse by proceeding type and year
plot_data <- proceedings |>
  filter(
    court == "Court of Justice" &
      decision_year >= 1989 &
      decision_year <= 2021
  ) |>
  group_by(proceeding_type, decision_year) |>
  summarize(
    mean = mean(ag_opinion) * 100
  )

# Make plot
plot <- ggplot(plot_data) +
  geom_line(aes(x = decision_year, y = mean, linetype = proceeding_type), size = 0.5, alpha = 1) +
  scale_linetype(name = NULL) +
  scale_x_continuous(breaks = seq(1990, 2020, 5)) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 20)) +
  theme_minimal() +
  titles_minimal(
    y = "Percentage of proceedings\nwith an AG opinion"
  ) +
  theme(
    legend.box.spacing = unit(25, "pt"),
    legend.position = "bottom",
    legend.direction = "vertical"
  )

# Save plot
ggsave("AG_opinions_over_time.pdf", plot, scale = 1.25, width = 10, height = 6)

# Application 2: The professional experience of judges -------------------------

## Experience heat map ---------------------------------------------------------

# Collapse by year and court
plot_data <- assignments |>
  filter(proceeding_year >= 1952 & proceeding_year <= 2021) |>
  filter(court %in% c("Court of Justice", "General Court")) |>
  group_by(court, proceeding_year) |>
  summarize(
    background_academic = mean(background_academic) * 100,
    background_civil_servant = mean(background_civil_servant) * 100,
    background_judge = mean(background_judge) * 100,
    background_politician = mean(background_politician) * 100,
    background_lawyer = mean(background_lawyer) * 100
  )

# Convert from wide to long format
plot_data <- pivot_longer(
  plot_data,
  cols = c(
    background_judge, background_academic, background_civil_servant,
    background_lawyer, background_politician
  ),
  names_to = "experience_type",
  values_to = "percent"
)

# Code variables
plot_data <- plot_data |>
  mutate(
    experience_type = case_when(
      experience_type == "background_politician" ~ "Politician",
      experience_type == "background_lawyer" ~ "Practicing lawyer",
      experience_type == "background_judge" ~ "Judge",
      experience_type == "background_civil_servant" ~ "Civil servant",
      experience_type == "background_academic" ~ "Academic"
    ),
    experience_type = factor(
      experience_type,
      levels = rev(c(
        "Judge", "Academic", "Civil servant",
        "Practicing lawyer", "Politician"
      ))
    ),
    court = case_when(
      court == "Court of Justice" ~ "Panel A: Court of Justice",
      court == "General Court" ~ "Panel B: General Court"
    ),
    percent = cut(
      percent,
      breaks = seq(0, 100, 10),
      include.lowest = TRUE
    )
  )

# Color palette
palette <- colorRampPalette(c("gray95", "gray20"))

# Make plot
plot <- ggplot(filter(plot_data)) +
  annotate("rect", xmin = 1954.5, xmax = 1988.5, ymin = 0.5, ymax = 5.5, fill = "gray95", color = "white", size = 0.5) +
  geom_tile(aes(x = proceeding_year, y = experience_type, fill = percent), color = "white", size = 0.5) +
  scale_fill_manual(values = palette(10), name = NULL) +
  scale_x_continuous(expand = c(0, 0), breaks = seq(1950, 2020, 10), limits = c(1954, 2019)) +
  scale_y_discrete(expand = c(0.2, 0)) +
  facet_wrap(vars(court), ncol = 1, nrow = 2, scales = "free_x") +
  theme_minimal() +
  titles_minimal() +
  theme(
    axis.line.y = element_blank(),
    axis.ticks.y = element_blank(),
    panel.spacing = unit(30, "pt"),
    legend.box.spacing = unit(30, "pt")
  )

# Save plot
ggsave("experience_over_time.pdf", plot, scale = 1.25, width = 10, height = 5)

## Experience maps -------------------------------------------------------------

# Collapse by year and court
plot_data <- assignments |>
  filter(proceeding_year >= 2004 & proceeding_year <= 2021) |>
  filter(court %in% c("Court of Justice", "General Court")) |>
  group_by(judge_member_state) |>
  summarize(
    background_judge = mean(background_judge) * 100,
    background_academic = mean(background_academic) * 100,
    background_civil_servant = mean(background_civil_servant) * 100,
    background_lawyer = mean(background_lawyer) * 100,
    background_politician = mean(background_politician) * 100
  )

# Adjust 0 values for color ramp
plot_data[plot_data == 0] <- 10e-5

# Map geography
geography <- create_geography(
  date = "2015-01-01",
  aspect_ratio = 1,
  zoom = 0.9,
  insets = c("Luxembourg", "Cyprus", "Malta")
)

# Map theme
theme <- create_theme(
  space_under_title = 16
)

# Panel A
panel_a <- make_map(
  geography = geography,
  palette = create_palette(
    member_states = plot_data$judge_member_state,
    values = plot_data$background_judge,
    value_min = 0,
    value_max = 100,
    count_colors = 5,
    color_low = c(0.8, 0.8, 0.8),
    color_high = c(0.3, 0.3, 0.3),
    color_non_member_state = c(0.95, 0.95, 0.95)
  ),
  theme = theme,
  title = "Panel A: Experience as a judge"
)

# Panel B
panel_b <- make_map(
  geography = geography,
  palette = create_palette(
    member_states = plot_data$judge_member_state,
    values = plot_data$background_academic,
    value_min = 0,
    value_max = 100,
    count_colors = 5,
    color_low = c(0.8, 0.8, 0.8),
    color_high = c(0.3, 0.3, 0.3),
    color_non_member_state = c(0.95, 0.95, 0.95)
  ),
  theme = theme,
  title = "Panel B: Experience as an academic"
)

# Panel C
panel_c <- make_map(
  geography = geography,
  palette = create_palette(
    member_states = plot_data$judge_member_state,
    values = plot_data$background_civil_servant,
    value_min = 0,
    value_max = 100,
    count_colors = 5,
    color_low = c(0.8, 0.8, 0.8),
    color_high = c(0.3, 0.3, 0.3),
    color_non_member_state = c(0.95, 0.95, 0.95)
  ),
  theme = theme,
  title = "Panel C: Experience as a civil servant"
)

# Panel D
panel_d <- make_map(
  geography = geography,
  palette = create_palette(
    member_states = plot_data$judge_member_state,
    values = plot_data$background_lawyer,
    value_min = 0,
    value_max = 100,
    count_colors = 5,
    color_low = c(0.8, 0.8, 0.8),
    color_high = c(0.3, 0.3, 0.3),
    color_non_member_state = c(0.95, 0.95, 0.95)
  ),
  theme = theme,
  title = "Panel D: Experience as a practicing lawyer"
)

# Combine plots
plot <- panel_a + panel_b + panel_c + panel_d + plot_layout(nrow = 2, ncol = 2)

# Save plot
ggsave("experience_by_member_state.pdf", plot, scale = 1.5, width = 10, height = 8)

# Application 3: Norms and conflicts of interest -------------------------------

## Preliminary ruling data -----------------------------------------------------

# Keep preliminary rulings
conflicts_rpr <- assignments |>
  filter(preliminary_ruling == 1) |>
  filter(court == "Court of Justice")

# Drop if there are multiple referring member states
conflicts_rpr <- conflicts_rpr |>
  filter(!str_detect(referring_member_state, ";"))

# Drop if the origin is not a member state
conflicts_rpr <- conflicts_rpr |>
  filter(referring_member_state != "other")

# Code conflict variable
conflicts_rpr <- conflicts_rpr |>
  rename(
    member_state = referring_member_state
  ) |>
  mutate(
    conflict = as.numeric(member_state == judge_member_state)
  )

# Organize variables
conflicts_rpr <- select(
  conflicts_rpr,
  cjeu_decision_id, decision_year,
  direct_action, preliminary_ruling,
  iuropa_judge_id, judge,
  judge_member_state, member_state, conflict
)

## Direct action data ----------------------------------------------------------

# Keep direct actions
conflicts_da <- assignments |>
  filter(direct_action == 1) |>
  filter(court == "Court of Justice")

# Get plaintiff data
plaintiffs <- judgments |>
  select(
    cjeu_decision_id, plaintiff
  ) |>
  filter(plaintiff %in% eums::member_states$member_state)

# Get defendant data
defendants <- judgments |>
  select(
    cjeu_decision_id, defendant
  ) |>
  filter(defendant %in% eums::member_states$member_state)

# Merge in plaintiffs data
conflicts_da <- left_join(
  conflicts_da,
  plaintiffs,
  by = "cjeu_decision_id"
)

# Merge in defendants data
conflicts_da <- left_join(
  conflicts_da,
  defendants,
  by = "cjeu_decision_id"
)

# Handle missing values
conflicts_da <- conflicts_da |>
  mutate(
    plaintiff = case_when(
      is.na(plaintiff) ~ "other",
      TRUE ~ plaintiff
    ),
    defendant = case_when(
      is.na(defendant) ~ "other",
      TRUE ~ defendant
    )
  )

# Drop direct actions in which a member state is not a party
conflicts_da <- conflicts_da |>
  filter(!(plaintiff == "other" & defendant == "other"))

# Code conflict variable
conflicts_da <- conflicts_da |>
  mutate(
    conflict = as.numeric(
      judge_member_state == plaintiff |
        judge_member_state == defendant
    ),
    member_state = case_when(
      plaintiff != "other" & defendant == "other" ~ plaintiff,
      plaintiff == "other" & defendant != "other" ~ defendant,
      plaintiff != "other" & plaintiff != "other" ~ "multiple"
    )
  ) |>
  filter(member_state != "multiple")

# Organize variables
conflicts_da <- conflicts_da |>
  select(
    cjeu_decision_id, decision_year,
    direct_action, preliminary_ruling,
    iuropa_judge_id, judge,
    judge_member_state, member_state, conflict
  )

## Descriptive statistics ------------------------------------------------------

# In what percent of judgments in preliminary rulings does a judge from the
# referring member state participate?
mean(conflicts_rpr$conflict)
summary <- conflicts_rpr |>
  group_by(cjeu_decision_id) |>
  summarize(
    conflict = as.numeric(sum(conflict) > 0)
  )
mean(summary$conflict)

# In what percent of judgments in direct actions at the Court of Justice in
# which one of the parties is a member state does a judge from that member state
# participate?
mean(conflicts_da$conflict)
summary <- conflicts_da |>
  group_by(cjeu_decision_id) |>
  summarize(
    conflict = as.numeric(sum(conflict) > 0)
  )
mean(summary$conflict)

## Conflicts of interest over time ---------------------------------------------

# Stack tibbles
plot_data <- bind_rows(conflicts_rpr, conflicts_da)

# Proceeding type
plot_data <- plot_data |>
  mutate(
    proceeding_type = case_when(
      preliminary_ruling == 1 ~ "References for a preliminary ruling",
      direct_action == 1 ~ "Direct actions"
    )
  )

# Organize variables
plot_data <- select(
  plot_data,
  cjeu_decision_id, decision_year, proceeding_type, conflict
)

# Collapse by decision and then by year
plot_data <- plot_data |>
  filter(decision_year >= 1989 & decision_year <= 2021) |>
  group_by(cjeu_decision_id, decision_year, proceeding_type) |>
  summarize(
    conflict = as.numeric(sum(conflict) > 0)
  ) |>
  group_by(decision_year, proceeding_type) |>
  summarize(
    conflict = mean(conflict) * 100,
  )

# make plot
panel_a <- ggplot(plot_data) +
  geom_line(aes(x = decision_year, y = conflict, linetype = proceeding_type), alpha = 1) +
  geom_vline(xintercept = 2004, linetype = "dashed") +
  scale_linetype(name = NULL) +
  scale_x_continuous(breaks = seq(1990, 2020, 5)) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 20)) +
  theme_minimal() +
  titles_minimal(
    title = "Panel A: Conflicts of interest over time",
    y = "Percentage of judgments\nwith a conflict of interest"
  ) +
  theme(
    panel.spacing = unit(30, "pt"),
    legend.position = "bottom",
    legend.direction = "vertical"
  )

## Conflicts of interest by member state ---------------------------------------

# Stack tibbles
plot_data <- bind_rows(conflicts_rpr, conflicts_da)

# Proceeding type
plot_data <- plot_data |>
  mutate(
    proceeding_type = case_when(
      preliminary_ruling == 1 ~ "References for a preliminary ruling",
      direct_action == 1 ~ "Direct actions"
    )
  )

# Organize variables
plot_data <- plot_data |>
  select(
    cjeu_decision_id, decision_year, member_state,
    proceeding_type, conflict
  )

# Collapse by decision
plot_data <- plot_data |>
  filter(decision_year >= 2004 & decision_year <= 2021) |>
  group_by(cjeu_decision_id) |>
  summarize(
    count = n(),
    conflict = as.numeric(sum(conflict) > 0),
    proceeding_type = proceeding_type[1],
    member_state = member_state[1]
  ) |>
  ungroup()

# Group by member state and proceeding type
plot_data <- plot_data |>
  group_by(member_state, proceeding_type) |>
  summarize(
    count = n(),
    conflict = mean(conflict) * 100,
    member_state = member_state[1]
  ) |>
  ungroup()

# Split data by procedure type
plot_data_b <- plot_data |>
  filter(proceeding_type == "Direct actions")
plot_data_c <- plot_data |>
  filter(proceeding_type == "References for a preliminary ruling")

# Order factor
plot_data_b <- plot_data_b |>
  mutate(
    member_state = fct_reorder(member_state, conflict)
  )
plot_data_c <- plot_data_c |>
  mutate(
    member_state = fct_reorder(member_state, conflict)
  )

# Make Panel B
panel_b <- ggplot(plot_data_b) +
  geom_segment(aes(x = -Inf, xend = conflict, y = member_state, yend = member_state), color = "gray90", size = 0.25) +
  geom_point(aes(x = conflict, y = member_state, size = count), color = "black") +
  scale_x_continuous(breaks = seq(0, 100, 5)) +
  scale_size_continuous(name = "Number of judgments") +
  theme_minimal() +
  titles_minimal(
    title = "Panel B: Conflicts of interest in direct actions",
    x = "Percentage of judgments in direct actions\nwith a conflict of interest",
    y = "Member state"
  ) +
  theme(
    panel.spacing = unit(30, "pt"),
    legend.position = "bottom",
    legend.direction = "vertical"
  )

# Make Panel C
panel_c <- ggplot(plot_data_c) +
  geom_segment(aes(x = -Inf, xend = conflict, y = member_state, yend = member_state, size = count), color = "gray90", size = 0.25) +
  geom_point(aes(x = conflict, y = member_state, size = count), color = "black") +
  scale_x_continuous(breaks = seq(0, 100, 5)) +
  scale_size_continuous(name = "Number of judgments") +
  theme_minimal() +
  titles_minimal(
    title = "Panel C: Conflicts of interest in preliminary rulings",
    x = "Percentage of judgments in preliminary rulings\nwith a conflict of interest"
  ) +
  theme(
    panel.spacing = unit(30, "pt"),
    legend.position = "bottom",
    legend.direction = "vertical"
  )

# Combine panels
plot_top <- panel_a
plot_bottom <- panel_b + panel_c + plot_layout(ncol = 2)
plot <- plot_top + plot_bottom + plot_layout(nrow = 2, heights = c(1, 2))

# Save plot
ggsave("conflicts_of_interest.pdf", plot, scale = 1.25, width = 10, height = 12)
